%% @author Bruno
%% @doc @todo Add description to controle_movimento.


-module(controle_movimento).

%% ====================================================================
%% API functions
%% ====================================================================
-export([iniciar/0, loop/1]).
-record(movimentador,{criaturas = [],executores=[], executoresLivres=[]}).

iniciar()->
	QtdExecutores = erlang:system_info(logical_processors_available) + 1,
	ListaExecutores = criarExecutores(QtdExecutores, []),
	InformacoesMovimentador = #movimentador{executores = ListaExecutores, executoresLivres = ListaExecutores},
	register(controle_movimento, spawn(controle_movimento, loop, [InformacoesMovimentador])).




loop(This)->
	QuantidadeCriaturas = length(This#movimentador.criaturas),
	Estado = estadoExecutores(This),
	if (QuantidadeCriaturas > 0) or (Estado =/= idle) ->
		   	receive
				{executor_livre, Pid} ->
					if QuantidadeCriaturas > 0 ->
						   [Criatura|T] = This#movimentador.criaturas,
						   Pid ! {movimentar, Criatura},
					   	   loop(This#movimentador{criaturas = T});
						true ->
						   loop(This#movimentador{executoresLivres = [Pid|This#movimentador.executoresLivres]})
					end;
				{parar_executores} ->
					loop(This#movimentador{criaturas = []})
			end;
		true ->
			receive
				{mover_criaturas, Criaturas}->
					simulador ! {aguardando_novo_ciclo},
					loop(This#movimentador{criaturas = Criaturas});
				{parar_executores} ->
					loop(This#movimentador{criaturas = []})
			end
	end.

%% ====================================================================
%% Internal functions
%% ====================================================================


estadoExecutores(This) ->
	NumExec = length(This#movimentador.executores),
	NumLivres = length(This#movimentador.executoresLivres),
	if NumLivres =:= NumExec ->
		   idle;
	   NumLivres < NumExec ->
		   running
	end.

criarExecutores(0, Lista)->
	Lista;
criarExecutores(QtdExecutores, Lista) ->
	Pid = spawn(movimentador, loop,[]),
	criarExecutores(QtdExecutores - 1,[Pid|Lista]).